﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Big2.Big2Game;
using Big2.CardsLib;
using System.ServiceModel;
using System.Threading;

namespace Big2.Big2WcfService
{
    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, UseSynchronizationContext = false)]
    public class Big2ServerService : IBig2ServerService
    {
        #region variables
        //thread sync lock object
        private static Object syncObj = new Object();
        string  xx ;
        //delegates
        public delegate List<string> LoginEventHandler(string name);
        public static event LoginEventHandler LoginCalled;

        public delegate int JoinGameEventHandler(string name);
        public static event JoinGameEventHandler JoinGameCalled;

        public delegate int PlayCardEventHandler(string name, List<Card> cardsToPlay);
        public static event PlayCardEventHandler PlayCardCalled;

        public delegate int PassEventHandler(string name);
        public static event PassEventHandler PassCalled;

        public delegate int TalkEventHandler(string name, string message);
        public static event TalkEventHandler TalkCalled;

        public delegate int LogoutEventHandler(string name);
        public static event LogoutEventHandler LogoutCalled;

        public delegate int StartGameEventHandler(string name);
        public static event StartGameEventHandler StartGameCalled;
        //end delegates

        ServiceHost serviceHost;
        Thread thread;
        public delegate void ServerStartedEventHandler();
        public static event ServerStartedEventHandler ServerStarted;
        public Connect Connection { get; set; }


        public static System.Collections.Generic.Dictionary<string, IBig2ServerServiceCallback> callbacks = new Dictionary<string, IBig2ServerServiceCallback>();
        public IBig2ServerServiceCallback Callback
        {
            get { return OperationContext.Current.GetCallbackChannel<IBig2ServerServiceCallback>(); }
        }
        #endregion


        #region constructors
        public Big2ServerService()
        {
            xx= Guid.NewGuid().ToString();
        }
        #endregion

        
        #region server functions
        public void startServer()
        {
            thread = new Thread(runServer);
            thread.IsBackground = true;
            thread.Start();
        }
        public void runServer()
        {
            //serviceHost.AddServiceEndpoint(typeof(IBig2ServerService), new NetTcpBinding(), "net.tcp://localhost:8010/Big2ServerService");
            serviceHost = new ServiceHost(typeof(Big2ServerService));
            serviceHost.Open();
            if (ServerStarted != null)
                ServerStarted();

        }
        public void CloseServer()
        {
            try
            {
                if (serviceHost.State == CommunicationState.Opened)
                {
                    serviceHost.Abort();
                    serviceHost.Close();
                }
            }
            catch { };
        }
        #endregion

        #region functions call by clients
        public List<string> Login(string name)
        {
            if(!callbacks.Keys.Contains(name)){
            //System.Diagnostics.EventLog.WriteEntry("Big2", "Login called in Big2Service");
            List<string> t = new List<string>();
            if (LoginCalled != null)
                t=LoginCalled(name);
            //PlayerJoin(name);       
            
            callbacks.Add(name,Callback);
            return t;

            }
            else
            {
                throw new Exception("Name already being used.");
            }
            
        }

        public int JoinGame(string name)
        {
            if (JoinGameCalled != null)
                return JoinGameCalled(name);
            return -1;
        }

        public int PlayCard(string name,List<Card> cardsToPlay)
        {
            if (PlayCardCalled!=null)
                return PlayCardCalled(name, cardsToPlay);
            return -1;
        }

        public int Pass(string name)
        {
            if (PassCalled!=null)
                PassCalled(name);
            return -1;
        }

        public int Talk(string name,string message)
        {
            //foreach (string key in callbacks.Keys)
            //{
            //    callbacks[key].NewTalkMSG(name + "--->" + message); 
            //}
            if (TalkCalled != null)
                TalkCalled(name, message);
            return 0;
        }

        public void Logout(string name)
        {
            if (LogoutCalled != null)
                LogoutCalled(name);
        }

        public void StartGame(string name)
        {
            if (StartGameCalled != null)
                StartGameCalled(name);
        }


        #endregion


        #region callback functions to the client

        public void PLayerLeft(string name)
        {
            foreach(string key in callbacks.Keys)
                if(String.Compare(name,key,true)!=0)
                    callbacks[key].PLayerLeft(name);
        }

        public void PlayerJoin(string name)
        {
            foreach (string key in callbacks.Keys)
                if (String.Compare(name, key, true) != 0)
                    callbacks[key].PlayerJoin(name);
        }

        public void GameStarted(List<string> playersInGame)
        {
            foreach (string key in callbacks.Keys)
                //if (String.Compare(name, key, true) != 0)
                callbacks[key].GameStarted(playersInGame);
        }

        public void DealHandToPlayer(string name,Hand hand)
        {
            callbacks[name].DealHandToPlayer(hand);
        }

        public void CurrentPlay(string name ,Big2.Big2Game.Play currentPLay)
        {
            callbacks[name].CurrentPlay(currentPLay);
        }

        public void PlayerTurn(string player,Play currentPlay)
        {
            callbacks[player].PlayerTurn(currentPlay);
        }

        public void GameEnd(string winnderName, List<Player> players)
        {
            foreach (Player p in players)
                callbacks[p.Name].GameEnd(winnderName,players);
           
        }

        public void NewTalkMSG(string msg)
        {
            foreach (string key in callbacks.Keys)
                //if (String.Compare(name, key, true) != 0)
                    callbacks[key].NewTalkMSG(msg);
        }       


        #endregion
    }
}
